<?php
/**
 * Copyright 2011  SURFfoundation
 * 
 * This file is part of ESCAPE.
 * 
 * ESCAPE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * ESCAPE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ESCAPE.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * For more information:
 * http://escapesurf.wordpress.com/
 * http://www.surffoundation.nl/
 * 
 * Contact: d.vierkant@utwente.nl
 * 
 * @license http://www.gnu.org/licenses/gpl.html GNU GPLv3
 */
?>
<?php
/**
 * Update ORE object property value
 * 
 * Update a property value of an ORE object.
 */
class escape_repositoryui_rpc_UpdateOreObjectPropertyValue extends escape_repositoryui_RpcHandler
{
	public $contentType = 'text/html';
	
	public function handleRequest()
	{
		$containerElementId = $_REQUEST['containerElementId'];
		$subject = $_REQUEST['subject'];
		$predicate = $_REQUEST['predicate'];
		$object = $_REQUEST['object'];
		$newObject = $_REQUEST['newObject'];
		// passing booleans through Ajax requests seems a little tricky, they end up as 'true' or 'false' strings?
		$single = false;
		if(isset($_REQUEST['single']) && ($_REQUEST['single'] == 'true' || $_REQUEST['single'] == 1))
		{
			$single = true;
		}
		
		// fetch the object and aggregation
		$oreObject = $this->repository->getOreObjectByUri($subject);
		if($oreObject === null)
		{
			throw new escape_repositoryui_exception_Exception('Failed to fetch the specified object');
		}
		$aggregation = $oreObject->getAggregation();
		
		// only administrators, editors and owners are allowed to update ore object property values
		$user = $this->repositoryUi->user;
		if($user === null || !($user->hasSystemRole(escape_repository_User::$role_administrator) || $aggregation->hasEditor($user->getUri()) || $aggregation->hasOwner($user->getUri())))
		{
			throw new escape_repositoryui_exception_Rpc("Not authorized");
		}

		if($object !== null && $object !== '' && $newObject == $object)
		{
			// nothing changed, ignore
			$this->repositoryUi->displayOreObjectEditorPropertyValueFragment($containerElementId, $subject, $predicate, $newObject, 'show', $single);
		}
		else
		{
			// check if we are updating the externalUri
			if($predicate === 'http://purl.utwente.nl/ns/escape-system.owl#externalUri')
			{
				//TODO: prevent show / resource URLs from items inside this aggregation (match by URI derived from ID in a URL starting with the server URL)?
				
				// generate a URI for objects without an external URI
				if($newObject === null || $newObject === "")
				{
					$newObject = $oreObject->getResourceUri();
				}
			}
			
			// check if an inverse statement exists
			$isOwlInverseFunctionalProperty = $this->repository->repositorySchema->isOwlInverseFunctionalProperty($predicate);
			
			$duplicateInverseFunctionalProperty = false;
			if($isOwlInverseFunctionalProperty)
			{
				$aggregatedResourceUris = $aggregation->getAggregatedResourceUrisHavingPredicateAndObject($predicate, $newObject);
				if(count($aggregatedResourceUris) > 0)
				{
					$duplicateInverseFunctionalProperty = true;
				}
			}
			
			if($isOwlInverseFunctionalProperty && $duplicateInverseFunctionalProperty)
			{
				// inverse statement exists, just show the editor with an error message
				print '<div class="escape_Error">Another property with the value \'' . htmlspecialchars($newObject) . '\' already exists in this aggregation</div>';
				$this->repositoryUi->displayOreObjectEditorPropertyValueFragment($containerElementId, $subject, $predicate, $object, 'edit', $single);
			}
			else
			{
				// no inverse statement exists, update the statement

				$oreObjectProperties = $oreObject->getProperties();
				
				
				if($newObject === null || $newObject === '')
				{
					// no new object provided, perform a remove action instead
					
					// remove matching relation annotations
					$relationAnnotations = $this->repository->getRelationAnnotationsBySubjectPredicateObject($subject, $predicate, $object);
					foreach($relationAnnotations as $relationAnnotation)
					{
						$relationAnnotation->delete();
					}
					
					// remove statement
					$oreObjectProperties->removeStatement($predicate, $object);
				}
				else
				{
					// check if the old statement exists
					if($oreObjectProperties->hasStatement($predicate, $object))
					{
						// old statement exists, update the statement
						$oreObjectProperties->replaceObject($predicate, $object, $newObject);
						
						// update matching relation annotations
						$relationAnnotations = $this->repository->getRelationAnnotationsBySubjectPredicateObject($subject, $predicate, $object);
						foreach($relationAnnotations as $relationAnnotation)
						{
							$rdfResource = $relationAnnotation->getProperties();
							$rdfResource->replaceObject('http://purl.utwente.nl/ns/escape-annotations.owl#object', $object, $newObject);

							// update last modified by
							$rdfResource->removeStatement('http://purl.utwente.nl/ns/escape-system.owl#lastModifiedBy');
							$rdfResource->addStatement('http://purl.utwente.nl/ns/escape-system.owl#lastModifiedBy', $user->getId());
							
							$relationAnnotation->setProperties($rdfResource);
						}
					}
					else
					{
						// old statement doesn't exist, perform an add action instead
						
						$oreObjectProperties->addStatement($predicate, $newObject);
					}
				}
				
				// update last modified by
				$oreObjectProperties->removeStatement('http://purl.utwente.nl/ns/escape-system.owl#lastModifiedBy');
				$oreObjectProperties->addStatement('http://purl.utwente.nl/ns/escape-system.owl#lastModifiedBy', $user->getId());
				
				// save the properties
				$oreObject->setProperties($oreObjectProperties);
				
				// display the result
				$this->repositoryUi->displayOreObjectEditorPropertyValueFragment($containerElementId, $subject, $predicate, $newObject, 'show', $single);
			}
		}
		
	}
}
